#include "OGLViewControl.h"

OGLViewControl::OGLViewControl()
{
	setDefaults();
}

OGLViewControl::~OGLViewControl()
{
}

OGLResult OGLViewControl::StartControl()
{
	camLoc = defaultCamLoc;
	camDir = defaultCamDir;
	camOrient = defaultCamOrient;

	fov = defaultFov;
	aspectRatio = defaultAspectRatio;
	rangeMin = defaultRangeMin;
	rangeMax = defaultRangeMax;

	matChanged = true;
	P = glm::lookAt(camLoc, camDir, camOrient);
	V = glm::perspective(fov, aspectRatio, rangeMin, rangeMax);

	return OGL_SUCCESS;
}

OGLResult OGLViewControl::StopControl()
{
	return OGL_SUCCESS;
}

glm::mat4 OGLViewControl::GetPVMat()
{
	if(matChanged)
	{
		matChanged = false;
		PV = P * V;
	}

	return PV;
}

void OGLViewControl::FirstUpdate()
{
	//V = glm::lookAt(camLoc, camDir, camOrient);
	//P = glm::perspective(fov + 0.2f, aspectRatio, rangeMin, rangeMax);
	//matChanged = true;
	camLoc = glm::vec3(
		r * cosf(phi) * sinf(theta), // x
		r * sinf(phi) * sinf(theta), // y
		r * cosf(theta) // z---+
	);
	camOrient = glm::vec3(cosf(phi), sinf(phi), 0);
	V = glm::lookAt(camLoc, camDir, camOrient);
	P = glm::perspective(fov + 0.2f, aspectRatio, rangeMin, rangeMax);
	matChanged = true;
}

void OGLViewControl::KeyboardActionHandler()
{
	bool keyPressed = false;
	if(glfwGetKey(GLFW_KEY_KP_ADD) == GLFW_PRESS)	// Zoom in
	{
		fov -= 0.5f;
		keyPressed = true;
	}
	if(glfwGetKey(GLFW_KEY_KP_SUBTRACT) == GLFW_PRESS)	// Zoom out
	{
		fov += 0.5f;
		keyPressed = true;
	}
	if(glfwGetKey('W') == GLFW_PRESS)
	{
		theta = std::min(theta + (float)DELTA_ANGLE, 0.0f);
		keyPressed = true;
	}
	if(glfwGetKey('S') == GLFW_PRESS)
	{
		theta = std::max(theta - (float)DELTA_ANGLE, -(float)M_PI_2 + (float)DELTA_ANGLE);		
		keyPressed = true;
	}
	if(glfwGetKey('A') == GLFW_PRESS)
	{
		phi -= (float)DELTA_ANGLE;
		if(phi <= -(M_PI * 2.0f))	// Keeps phi in range (-2 * PI, 2 * PI)
			phi += (float)(M_PI * 2.0f);
		keyPressed = true;
	}
	if(glfwGetKey('D') == GLFW_PRESS)
	{
		phi += (float)DELTA_ANGLE;
		if(phi >= M_PI * 2.0f)		// Keeps phi in range (-2 * PI, 2 * PI)
			phi -= (float)(M_PI * 2.0f);
		keyPressed = true;
	}
	if(keyPressed)
	{
		camLoc = glm::vec3(
			r * cosf(phi) * sinf(theta), // x
			r * sinf(phi) * sinf(theta), // y
			r * cosf(theta) // z---+
		);
		camOrient = glm::vec3(cosf(phi), sinf(phi), 0);
		V = glm::lookAt(camLoc, camDir, camOrient);
		P = glm::perspective(fov, aspectRatio, rangeMin, rangeMax);
		matChanged = true;
	}
}

void OGLViewControl::MouseActionHandler()
{}

void OGLViewControl::setDefaults()
{
	// Set Default Camera parameters
	r = 200.0f;
//	theta = (float)M_PI_2;
	theta = 0.0f;
	phi = 0.0f;
	defaultCamLoc = glm::vec3(0.0f, 0.0f, r);	// Top-down view
	defaultCamDir = glm::vec3(0.0f, 0.0f, 0.0f);	// Points at origin
	defaultCamOrient = glm::vec3(0.0f, 1.0f, 0.0f);	// Oriented right-side-up

	// Set Default Schene parameters
	defaultFov = 45.0f;
	defaultAspectRatio = 16.0f / 9.0f;
	defaultRangeMin = 0.01f;
	defaultRangeMax = 1000.0f;
	
	// Set default View and Projection matrices
	matChanged = true;
	P = glm::perspective(defaultFov, defaultAspectRatio, defaultRangeMin, defaultRangeMax);
	V = glm::lookAt(defaultCamLoc, defaultCamDir, defaultCamOrient);
}